package com.zelin.seckill.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zelin.dao.PayLogDao;
import com.zelin.dao.SeckillGoodsDao;
import com.zelin.dao.SeckillOrderDao;
import com.zelin.entity.PayLogEntity;
import com.zelin.entity.SeckillGoodsEntity;
import com.zelin.entity.SeckillOrderEntity;
import com.zelin.entity.SeckillStatus;
import com.zelin.entity.vo.PayVo;
import com.zelin.seckill.service.SeckillOrderService;
import com.zelin.seckill.service.task.MultiThreadingCreateOrder;
import com.zelin.utils.StatusCode;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundHashOperations;
import org.springframework.data.redis.core.StringRedisTemplate;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * ------------------------------
 * 功能：
 * 作者：WF
 * 微信：hbxfwf13590332912
 * 创建时间：2021/8/19-15:57
 * ------------------------------
 */
@Service
public class SeckillOrderServiceImpl extends ServiceImpl<SeckillOrderDao, SeckillOrderEntity>  implements SeckillOrderService {
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private SeckillGoodsDao seckillGoodsDao;
    @Autowired
    private MultiThreadingCreateOrder multiThreadingCreateOrder;
    /**
     * 功能: 保存订单
     * 参数:
     * 返回值: boolean
     * 时间: 2021/8/19 15:57
     */
    @Override
    public boolean save(String secKillId, String time, String username)  {
        // 定义用户状态信息保存到redis中的队列中
        SeckillStatus seckillStatus = new SeckillStatus(username,new Date(),1, Long.parseLong(secKillId),time);

        //1. 避免重复排队
        //定义以当前登录名为key的自增值，它只能自增一次（因为每个用户只准添加一次到队列中）,返回自增后的值
        Long queueCount = redisTemplate.boundHashOps("UserQueueCount").increment(username, 1);
        if(queueCount > 1){
            throw new RuntimeException(StatusCode.REPERROR + "");
        }

        //2. 公平购买商品(根据排队的顺序下单)
        // 将此对象入队列,目的是为了公平原则（先排队先下单）
        redisTemplate.boundListOps("SeckillOrderQueue").leftPush(JSON.toJSONString(seckillStatus));

        //3. 将订单状态备份
        // 为了后面查询订单状态，我们将上面的seckillStatus又保存一份到redis中（因上面的会被立即弹出）
        redisTemplate.boundHashOps("UserQueueStatus").put(username,JSON.toJSONString(seckillStatus));

        //4. 异步下单
        multiThreadingCreateOrder.createOrder();

        return true;
    }
    //根据用户名查询用户的秒杀状态
    @Override
    public SeckillStatus querySeckillStatus(String name) {
        String status = (String) redisTemplate.boundHashOps("UserQueueStatus").get(name);
        return JSON.parseObject(status,SeckillStatus.class);
    }

    /**
     * 功能: 从redis中查询出秒杀订单并返回payVo
     * 参数:
     * 返回值: com.zelin.entity.vo.PayVo
     * 时间: 2021/8/20 16:51
     */
    @Override
    public PayVo getPayVo(String name) {
        String orderStr = (String) redisTemplate.boundHashOps("SeckillOrder").get(name);
        SeckillOrderEntity orderEntity = JSON.parseObject(orderStr, SeckillOrderEntity.class);
        PayVo payVo = new PayVo();
        payVo.setTotal_amount(orderEntity.getMoney() + "");
        payVo.setSubject("秒杀订单");
        payVo.setBody("泽易购秒杀");
        payVo.setOut_trade_no(orderEntity.getId() + "");
        return payVo;
    }

    /**
     * 功能: 从redis中通过登录名得到订单列表
     * 参数: 
     * 返回值:com.zelin.entity.SeckillOrderEntity
     * 时间: 2021/8/20 17:44
     */
    @Override
    public SeckillOrderEntity findOrderList(String name) {
        BoundHashOperations<String, String, String> hashOperations = redisTemplate.boundHashOps("SeckillOrder");
        String s = hashOperations.get(name);

        return JSON.parseObject(s,SeckillOrderEntity.class);
    }

    @Override
    public List<SeckillOrderEntity> findOrders(String name) {
        List<SeckillOrderEntity> orderEntities = this.list(new QueryWrapper<SeckillOrderEntity>().eq("user_id", name));
        for (SeckillOrderEntity orderEntity : orderEntities) {
            SeckillGoodsEntity goodsEntity = seckillGoodsDao.selectById(orderEntity.getSeckillId());
            System.out.println("goodsEntity = " + goodsEntity);
            orderEntity.setGoodsEntity(goodsEntity);
        }
        return orderEntities;
    }
}

